﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlClient;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using QQ2564874169.Core.ORM;

namespace Tests.RelationalSql
{
    [TestClass]
    public class 数据库基础操作
    {
        [TestMethod]
        public void 事务嵌套时提交次数需要和开启次数一致才会真正提交()
        {
            var count = 0;
            using (var sql = new MockSql())
            {
                sql.TransactionAfter += (s, e) =>
                {
                    if (e.IsCommited)
                        count++;
                };
                using (var t = sql.Transaction())
                {
                    using (var t2 = sql.Transaction())
                    {
                        using (var t3 = sql.Transaction())
                        {
                            t3.Commit();
                        }
                        t2.Commit();
                    }
                    t.Commit();
                }
            }
            Assert.AreEqual(1, count);
        }

        [TestMethod]
        public void 子事务回滚后Sql在事务外还可以使用()
        {
            var count = 0;
            using (var sql = new MockSql())
            {
                sql.Rs = 1;
                using (var t = sql.Transaction())
                {
                    sql.Execute("insert into");
                    count++;
                    using (var t2 = sql.Transaction())
                    {
                        sql.Execute("insert into");
                        count++;
                        t2.Rollback();
                        try
                        {
                            sql.Execute("insert into");
                        }
                        catch
                        {
                            count++;
                        }
                    }

                    try
                    {
                        sql.Execute("insert into");
                    }
                    catch
                    {
                        count++;
                    }
                    t.Rollback();
                }
                sql.Execute("insert into");
                count++;
            }

            Assert.AreEqual(5, count);
        }


        [TestMethod]
        public void 子事务回滚后Sql在事务内无法再使用()
        {
            var count = 0;
            using (var sql = new MockSql())
            using (var t = sql.Transaction())
            {
                sql.Rs = 1;
                sql.Execute("insert into");
                count++;
                using (var t2 = sql.Transaction())
                {
                    sql.Execute("insert into");
                    count++;
                    t2.Rollback();
                    try
                    {
                        sql.Execute("insert into");
                    }
                    catch
                    {
                        count++;
                    }
                }

                try
                {
                    sql.Execute("insert into");
                }
                catch
                {
                    count++;
                }
            }

            Assert.AreEqual(4, count);
        }

        private static void CheckParam(object param, IDictionary<string, object> spvs)
        {
            var count = 0;
            using (var sql = new MockSql())
            {
                sql.Rs = 1;
                sql.Before += (s, e) =>
                {
                    foreach (var item in e.Context.Param)
                    {
                        if (spvs.ContainsKey(item.Key))
                        {
                            if (spvs[item.Key].Equals(item.Value))
                                count++;
                        }
                    }
                };
                sql.Execute("sql", param);
            }
            Assert.AreEqual(spvs.Count, count);
        }

        [TestMethod]
        public void Object参数()
        {
            var date = DateTime.Now;
            CheckParam(
                new { a = 1, b = "2", date },
                new Dictionary<string, object>
                {
                    {"a", 1},
                    {"b", "2"},
                    {"date", date}
                });
        }

        [TestMethod]
        public void Dictionary参数()
        {
            var date = DateTime.Now;
            CheckParam(
                new Hashtable
                {
                    {"a", 1},
                    {"b", "2"},
                    {"date", date}
                },
                new Dictionary<string, object>
                {
                    {"a", 1},
                    {"b", "2"},
                    {"date", date}
                });
        }
    }
}
